/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.formserver.vmmanager.util;

import com.inspur.edp.bef.bizentity.pushchangesetargs.ActionChangeDetail;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ActionChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ChangeType;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ElementChangeDetail;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ElementChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ObjectChangeDetail;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ObjectChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.PushChangeSet;
import com.inspur.edp.bef.bizentity.util.StringUtil;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import com.inspur.edp.formserver.viewmodel.common.ConvertUtils;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementSourceType;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoObjectSourceType;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.util.List;


public class PushChangeSets {

    /**
     * @param metadata  元数据
     * @param changeSet 推送变更集
     */
    public PushChangeSets(GspMetadata metadata, PushChangeSet changeSet) {
        this.metadata = metadata;
        this.actionChangeSets = changeSet.getActionChangeSets();
        this.objectChangeSets = changeSet.getObjectChangeSets();
        this.elementChangeSets = changeSet.getElementChangeSets();
    }

    private GspMetadata metadata;
    private List<ActionChangeSet> actionChangeSets;
    private List<ObjectChangeSet> objectChangeSets;
    private List<ElementChangeSet> elementChangeSets;

    /**
     * 推送元数据
     */
    public void pushChangeSetToMetadata() {
        pushActionChangeSets();
        pushObjectChangeSets();
        pushElementChangeSets();
        saveMetadata();
    }

    /**
     * 推送MgrAction
     */
    private void pushActionChangeSets() {
        if (this.actionChangeSets == null | this.actionChangeSets.size() == 0) {
            return;
        }
        this.actionChangeSets.forEach(set -> {
            pushAction(set);
        });
    }

    /**
     * 保存元数据
     */
    private void saveMetadata() {
        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
        metadataService.saveMetadata(metadata, CheckInfoUtil.getCombinePath(metadata.getRelativePath(), metadata.getHeader().getFileName()));
    }

    private void pushAction(ActionChangeSet set) {
        ActionChangeDetail detail = set.getChangeDetail();
        PushActionChangeSet pushAction = new PushActionChangeSet();

        ViewModelAction orgAction = pushAction.getMgrActionByID(this.metadata, detail.getActionId());
        ViewModelAction newAction = null;
        if (set.getChangeDetail().getMgrAction() != null) {
            newAction = ConvertUtils.toMappedAction(set.getChangeDetail().getMgrAction(), ((GspViewModel) metadata.getContent()).getID(), "");
        }

        // 新增 动作
        if (set.getChangeType().equals(ChangeType.Add) && orgAction == null && newAction != null) {
            pushAction.AddMgrAction(metadata, newAction);
            return;
        }

        // 新增参数

        if (set.getChangeType().equals(ChangeType.Add) && orgAction != null && newAction != null) {
            if (StringUtil.checkNull(set.getChangeDetail().getParameterId())) {
                return;
            }
            pushAction.addMgrActionParam(orgAction, newAction, detail.getParameterCode());
        }
        // 修改
        if (set.getChangeType().equals(ChangeType.Modify) && orgAction != null) {
            pushAction.ModifyAction(orgAction, newAction, detail);
            return;
        }

        if (set.getChangeType().equals(ChangeType.Delete) && StringUtil.checkNull(detail.getParameterCode())) {
            pushAction.deleteMgrAction(metadata, detail.getActionCode());
            return;
        }
        if (set.getChangeType().equals(ChangeType.Delete) && !StringUtil.checkNull(detail.getParameterCode())) {
            pushAction.deleteMgrActionPara(orgAction, detail.getParameterCode());
            return;
        }
    }

    private void pushObjectChangeSets() {
        if (this.objectChangeSets == null || this.objectChangeSets.size() == 0) {
            return;
        }
        this.objectChangeSets.forEach(set -> {
            pushObject(set);
        });

    }

    private void pushObject(ObjectChangeSet set) {
        ObjectChangeDetail detail = set.getChangeDetail();
        PushObjectChangeSet pushObject = new PushObjectChangeSet();
        GspViewObject orgObject = pushObject.getObjectByID(this.metadata, detail.getBizObjectId());

        // 新增节点
        if (set.getChangeType().equals(ChangeType.Add)) {
            // 根据父对象ID获取对应的VO对象
            String parentObjID = detail.getParentObjIDElementId();
            GspViewObject parentVoObj = pushObject.getObjectByID(this.metadata, parentObjID);
            GspViewObject newObject = null;
            if (set.getChangeDetail().getBizObject() != null) {
                newObject = ConvertUtils.toObject(set.getChangeDetail().getBizObject(),
                        ((GspViewModel) metadata.getContent()).getMapping().getTargetMetadataPkgName(),
                        ((GspViewModel) metadata.getContent()).getMapping().getTargetMetadataId(),
                        parentVoObj, GspVoObjectSourceType.BeObject);
            }
            if (newObject != null && !parentObjectHasBeenAdded(parentObjID)) {
                pushObject.addObject(metadata, newObject, parentObjID);
                return;
            }
        }
        // 修改节点
        if (set.getChangeType().equals(ChangeType.Modify) && orgObject != null) {
            pushObject.modifyObject(orgObject, set.getChangeDetail());
            return;
        }
        //删除节点
        if (set.getChangeType().equals(ChangeType.Delete)) {
            pushObject.deleteObject(metadata, detail.getBizObjectId());
        }

    }

    private boolean parentObjectHasBeenAdded(String parentObjId) {
        for (ObjectChangeSet set : this.objectChangeSets) {
            if (set.getChangeType().equals(ChangeType.Add) && set.getChangeDetail().getBizObjectId().contains(parentObjId)) {
                return true;
            }
        }
        return false;
    }

    private void pushElementChangeSets() {
        if (this.elementChangeSets == null || this.elementChangeSets.size() == 0) {
            return;
        }
        this.elementChangeSets.forEach(set -> {
            pushElement(set);
        });
    }

    private void pushElement(ElementChangeSet set) {
        ElementChangeDetail detail = set.getChangeDetail();
        PushElementChangeSet pushElement = new PushElementChangeSet();
        GspViewObject orgObject = pushElement.getObjectByID(metadata, detail.getBizObjectId());
        if (orgObject == null) {
            return;
        }
        GspViewModelElement orgElement = pushElement.getElementById(orgObject, detail.getBizElementId());
        GspViewModelElement newElement = null;
        if (set.getChangeDetail().getBizElement() != null) {
            newElement = ConvertUtils.toElement(
                    set.getChangeDetail().getBizElement(),
                    ((GspViewModel) metadata.getContent()).getMapping().getTargetMetadataPkgName(),
                    ((GspViewModel) metadata.getContent()).getMapping().getTargetMetadataId(),
                    GspVoElementSourceType.BeElement);

            //TODO:目前不支持一个字段关联多个be上的字段，因此未考虑ChildAssociation数组含有多个关联的情况，支持一对多的关联后需修改
            if (set.getType().equals(ChangeType.Modify) && orgElement != null) {
                if (newElement.getChildAssociations() != null && orgElement.getChildAssociations() != null && newElement.getChildAssociations().size() > 0 && orgElement.getChildAssociations().size() > 0) {
                    for (IGspCommonField newField : newElement.getChildAssociations().get(0).getRefElementCollection()) {
                        for (IGspCommonField orgField : orgElement.getChildAssociations().get(0).getRefElementCollection()) {
                            if (newField.getCode() != null && newField.getCode().equals(orgField.getCode())) {
                                newField.setID(orgField.getID());
                            }
                        }
                    }
                }
            }

        }

        // 新增
        if (set.getType().equals(ChangeType.Add) && orgElement == null && newElement != null) {
            pushElement.addElement(orgObject, newElement);
            return;
        }
        // 修改
        if (set.getType().equals(ChangeType.Modify) && orgElement != null) {
            pushElement.modifyElement(orgElement, newElement, detail);
        }
        // 删除
        if (set.getType().equals(ChangeType.Delete)) {
            pushElement.deleteElement(orgObject, detail.getBizElementId());
        }

    }

}
